﻿using System;
using System.Linq;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using Services.Implementations;
using Services.Models;

namespace Socaloud.Broadcast {

    [HubName("leaguesTicker")]
    public class LeaguesHub : Hub {

        private readonly LeaguesTicker _leaguesTicker;

        public LeaguesHub()
            : this(LeaguesTicker.Instance) {

        }

        public LeaguesHub(LeaguesTicker leaguesTicker) {
            _leaguesTicker = leaguesTicker;
        }

        public IEnumerable<LeagueWithMatchesModel> GetLeagues() {
            Groups.Add(Context.ConnectionId, "all");
            return _leaguesTicker.GetLeagues();
        }

    }

    public class LeaguesTicker {

        private readonly static Lazy<LeaguesTicker> _instance = new Lazy<LeaguesTicker>(() => new LeaguesTicker(GlobalHost.ConnectionManager.GetHubContext<LeaguesHub>().Clients));

        public static LeaguesTicker Instance {
            get { return _instance.Value; }
        }

        private Timer _timer;

        private IHubConnectionContext Clients {
            get;
            set;
        }

        private readonly object _updateLock = new object();
        private volatile bool _updating = false;
        private readonly ConcurrentDictionary<string, LeagueWithMatchesModel> _leagues = new ConcurrentDictionary<string, LeagueWithMatchesModel>();

        public LeaguesTicker(IHubConnectionContext clients) {
            Clients = clients;
            var leagues = new XmlSoccerService().GetLeaguesWithMaches().ToList();
            leagues.ForEach(x => _leagues.TryAdd(x.League, x));
            var updateInterval = TimeSpan.FromMilliseconds(2500);
            _timer = new Timer(UpdateLeagues, null, updateInterval, updateInterval);
        }

        private void UpdateLeagues(object state) {
            lock(_updateLock) {
                if(!_updating) {

                    _updating = true;
                    var leagues = new XmlSoccerService().GetLeaguesWithMaches().ToList();

                    //if(leagues.Equals(_leagues)) {
                    //_leagues = leagues;
                    _leagues.Clear();
                    leagues.ForEach(x => _leagues.TryAdd(x.League, x));
                    Clients.Group("all").updateLeagues(_leagues.Values);
                    //}

                    _updating = false;
                }
            }
        }

        public IEnumerable<LeagueWithMatchesModel> GetLeagues() {
            return _leagues.Values;
        }
    }

}